/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package uk.ac.cam.juliet.zedcat.client;

import java.awt.Color;
import java.awt.image.BufferedImage;

/**
 *
 * @author Chris
 */
public class RGBHistogram implements ImageSignature {

    // Bin parameters.
    int r_bins = 6;
    int g_bins = 6;
    int b_bins = 6;
    int histogram_height = 512;

    BufferedImage image;
    Color nullColour = new Color(0);
    double[][][] histogram;
    boolean generated = false;

    public RGBHistogram() {
    }

    public float getDistance(ImageSignature is) throws Exception {
        if (!generated)
            throw new Exception("You can't get a distance with an uninitialised ImageSignature.");
        float distance = 0;

        for (int r = 0; r < r_bins; ++r)
            for (int g = 0; g < g_bins; ++g)
                for (int b = 0; b < b_bins; ++b) {
                   // Histogram Intersection (maybe)
                   // distance += (float) min(this.histogram[h][s][v], ((int[][][])is.getSignature())[h][s][v]);
                   // Euclidean Distance
                   distance += Math.pow(this.histogram[r][g][b] - ((double[][][])is.getSignature())[r][g][b], 2);
                }

        return distance;
    }

    private void makeHistogram() {

        // Initialise
        histogram = new double[r_bins][g_bins][b_bins];
        int pixelCount = 0;
        Color pixColour;
        float[] HSV;

        // Fill the bins.
        for (int x = 0; x < image.getWidth(); ++x) {
            for (int y = 0; y < image.getHeight(); ++y) {

                pixColour = new Color(image.getRGB(x,y));
                if ( pixColour == nullColour )
                    continue;
                ++pixelCount;

                ++histogram[(int) Math.floor(((pixColour.getRed() / (float) 256) * r_bins) * 0.99999)]
                           [(int) Math.floor(((pixColour.getGreen() / (float) 256) * r_bins) * 0.99999)]
                           [(int) Math.floor(((pixColour.getBlue() / (float) 256) * r_bins) * 0.99999)];

            }
        }

        // Normalise the bins
        for (int r = 0; r < r_bins; ++r)
            for (int g = 0; g < g_bins; ++g)
                for (int b = 0; b < b_bins; ++b) {
                    histogram[r][g][b] = (histogram[r][g][b] * histogram_height) / pixelCount;
                    if (r==5 && g==2)
                        System.out.println(histogram[r][g][b]);
                }

        System.out.println("Pixels: " + pixelCount +
                           " Scaling factor: " + (histogram_height / (float) pixelCount));

        generated = true;
    }

    private double max (double a, double b) {
        if (a > b) return a;
        return b;
    }

    private int min (int a, int b) {
        if (a < b) return a;
        return b;
    }

    public Object getSignature() {
        makeSignature();
        return histogram;
    }

    public void makeSignature() {
        if (!generated)
            makeHistogram();
    }

    public void setImage(BufferedImage r) {
        image = r;
        generated = false;
    }

    public void setNullColour(Color c) {
        nullColour = c;
        generated = false;
    }

}
